#!/usr/bin/env python
# encoding: utf-8
import datetime
import json
import os
import re
from copy import deepcopy

import numpy as np
import pandas as pd

from feature_set.base_feature import BaseFeature
from feature_set.call.un.call_un_base0_v1.CallUnBase0V1Module1 import (
    CallUnBase0V1Module1,
)
from feature_set.call.un.call_un_base0_v1.CallUnBase0V1Module2 import (
    CallUnBase0V1Module2,
)
from feature_set.call.un.call_un_base0_v1.CallUnBase0V1Module3 import (
    CallUnBase0V1Module3,
)
from feature_set.call.un.call_un_base0_v1.CallUnBase0V1Module4 import (
    CallUnBase0V1Module4,
)
from feature_set.call.un.call_un_base0_v1.CallUnBase0V1Module5678 import (
    CallUnBase0V1Module5678,
)

m1_class = CallUnBase0V1Module1()
m2_class = CallUnBase0V1Module2()
m3_class = CallUnBase0V1Module3()
m4_class = CallUnBase0V1Module4()
m5678_class = CallUnBase0V1Module5678()


class CallUnBase0V1(BaseFeature):
    def __init__(self):
        super().__init__()
        ##定位根目录
        self.root_dir = self.get_root_dir(os.path.abspath("."))
        ##定位配置文件目录
        self.conf_dir = os.path.join(self.root_dir, "feature_conf")
        
        self.feature_list = self.init_feature_list()
        
        ##不同子模块对应计算函数
        self.function_map = {
            "def": self.compute_module1,
            "comp": self.compute_module2,
            "timediff": self.compute_module3,
            "sos": self.compute_module4,
            "": self.compute_module5678,
        }
        ##需要根据不同国家进行重写
        self.country_info = None
        self.type_trans_hash = None
        self.duration_name = None
        self.calltime_name = None
        self.phone_name = None
        self.name_name = None
        self.type_name = None

    def load_conf(self):
        pass

    ##对传来的数据进行规范化处理
    def load_request(self, request_data):
        apply_time = self.trans_str_to_time(request_data.apply_time)
        try:
            call_list = []
            calllog_data = request_data.data_sources["calllog_data"]
            call_list = (
                json.loads(calllog_data) if type(calllog_data) == str else calllog_data
            )
        except:
            pass
        try:
            contact_phone_list = []
            contact_list = request_data.data_sources["contact_list"]
            contact_list = (
                json.loads(contact_list) if type(contact_list) == str else contact_list
            )
            for contact in contact_list:
                contact_phone_list.append(contact["contactPhoneNumber"])
        except:
            pass
        if len(call_list) == 0 or type(call_list) != list:
            assert (
                1 == 0
            ), "传入的call_json无法解析或者解析后异常(不是list，或者为空list)"
        if len(contact_phone_list) == 0 or type(contact_phone_list) != list:
            assert (
                1 == 0
            ), "传入的contact_json无法解析或者解析后异常(不是list，或者为空list)"
        

        name_trans_hash = {
            "duration": self.duration_name,
            "calltime": self.calltime_name,
            "type": self.type_name,
            "phone": self.phone_name,
            "name": self.name_name,
        }

        clean_call_list = []
        for call in call_list:
            trans_call = {}
            trans_call["duration"] = call[name_trans_hash["duration"]]
            trans_call["calltime"] = datetime.datetime.utcfromtimestamp(
                int(call[name_trans_hash["calltime"]]) // 1000
            ) + datetime.timedelta(hours=self.country_info["time_zone"])
            trans_call["phone"] = self.normalize_phone(
                self.country_info["phone_len"], call.get(name_trans_hash["phone"], "")
            )
            trans_call["name"] = (
                call.get(name_trans_hash["name"], "")
                if call.get(name_trans_hash["name"], "") != "-999"
                else ""
            )
            trans_call["type"] = self.type_trans_hash.get(
                call[name_trans_hash["type"]], "5"
            )
            trans_call["diff_days"] = (
                apply_time.date() - trans_call["calltime"].date()
            ).days
            if trans_call["calltime"] <= self.trans_str_to_time(
                request_data.apply_time
            ):
                clean_call_list.append(deepcopy(trans_call))

        clean_contact_phone_list = []
        for phone in contact_phone_list:
            phone = self.normalize_phone(self.country_info["phone_len"], phone)
            clean_contact_phone_list.append(phone)

        self.data = {
            "call_list": clean_call_list,
            "contact_phone_list": clean_contact_phone_list,
            "apply_time": apply_time,
            "country_info": self.country_info,
        }

    def init_feature_list(self):
        feature_list = []
        feature_name_path = os.path.join(self.root_dir, "feature_set/call/un/call_un_base0_v1/feature_name")
        with open(feature_name_path, 'r') as f:
            for line in f:
                feature_list.append(line.strip())
        return feature_list

    ###特征计算函数
    def gen_features(self, request_data):
        self.load_conf()
        res_map = {}
        try:
            self.load_request(request_data)
            assert len(self.data["call_list"]) > 0, "call_list为空"
        except:
            for k in self.feature_list:
                if k not in ['se_del_nullmax(30)_end_date',
                        'se_del_nullmax(30)_start_date',
                        'se_end_date',
                        'se_start_date']:
                    res_map[k] = -999
                else:   
                    res_map[k] = ""
            return res_map
        for prefix, function in self.function_map.items():
            res_map_ = function()
            if prefix:
                prefix = prefix + "_"
            for feature_name, feature_value in res_map_.items():
                if feature_value == "None" or pd.isna(feature_value):
                    if prefix + feature_name not in ['se_del_nullmax(30)_end_date',
                                                    'se_del_nullmax(30)_start_date',
                                                    'se_end_date',
                                                    'se_start_date']:
                        res_map[prefix + feature_name] = -999
                    else:
                        res_map[prefix + feature_name] = ""
                else:
                    if type(feature_value) == np.int64:
                        res_map[prefix + feature_name] = int(feature_value)
                    else:
                        res_map[prefix + feature_name] = feature_value
                
        return res_map

    ###子模块计算函数
    def compute_module1(self):
        return m1_class.main(deepcopy(self.data))

    def compute_module2(self):
        return m2_class.main(deepcopy(self.data))

    def compute_module3(self):
        return m3_class.main(deepcopy(self.data))

    def compute_module4(self):
        return m4_class.main(deepcopy(self.data))

    def compute_module5678(self):
        return m5678_class.main(deepcopy(self.data))

    ###下面为help函数

    ##标准化电话号
    def normalize_phone(self, phone_len, phone):
        phone = str(phone)
        phone = re.findall(r"[0-9]*", phone)
        phone = "".join(phone)
        phone = phone[-phone_len:]
        return phone

    ###字符串转datatime
    def trans_str_to_time(self, str_time):
        return datetime.datetime.strptime(str_time, "%Y-%m-%d %H:%M:%S")

    ###定位根目录
    def get_root_dir(self, path):
        path_list = path.split(os.path.sep)
        index = path_list.index("featurelib")
        return os.path.sep.join(path_list[: index + 1])
